package schedulo.gui.components;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.LinkedList;

import javax.swing.JEditorPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import schedulo.core.task.ParseMessage;
import schedulo.core.task.Task;
import schedulo.core.task.provider.TaskProvider;
import schedulo.core.task.provider.TaskProviderListener;

public class TaskEditorTab extends JPanel implements TaskProviderListener {

	private static final long serialVersionUID = 509829827987L;

	private JScrollPane scrollPane;

	private JEditorPane editorPane;

	private TaskProvider taskProvider;
	
	private boolean editing;

	public TaskEditorTab(TaskProvider provider) {
		super();
		setLayout(new GridBagLayout());
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.anchor = GridBagConstraints.NORTHWEST;
		gbc.fill = GridBagConstraints.BOTH;
		gbc.weightx = 1.0;
		gbc.weighty = 1.0;
		editorPane = new JEditorPane();
		editorPane.addKeyListener(new EditorPaneKeyAdapter());
		scrollPane = new JScrollPane(editorPane);
		add(scrollPane, gbc);
		taskProvider = null;
		
		editing = false;

		setTaskProvider(provider);
	}

	class EditorPaneKeyAdapter extends KeyAdapter {
		public void keyReleased(KeyEvent e) {

			editing = true;
			
			String text = editorPane.getText();
			LinkedList<Task> tasks = new LinkedList<Task>();
			try {
				LinkedList<ParseMessage> parseMessages = Task.load(
						new ByteArrayInputStream(text.getBytes()), tasks);

				// show log
				// Task.save(tasks, System.out);

				// set tasks to the TaskProvider
				if (taskProvider != null) {
					taskProvider.setTaskList(tasks);
				}

				setChanged();

				// process CTRL-S
				if (e.isControlDown() && e.getKeyCode() == KeyEvent.VK_S) {
					save();
				}

			} catch (IOException e1) {
				e1.printStackTrace();
			}
			
			editing = false;
		}
	}

	private void setChanged() {
		// update editor content
		taskProviderUpdated(taskProvider);
	}

	private void save() throws IOException {
		System.out.println("Save this provider");
		taskProvider.save();

		// update editor content
		updateContent();
	}

	public void setTaskProvider(TaskProvider provider) {

		// detach from previous task provider if any
		if (taskProvider != null) {
			taskProvider.removeTaskProviderListener(this);
		}

		taskProvider = provider;

		// attach to new task provider
		taskProvider.addTaskProviderListener(this);

		// update editor content
		updateContent();
	}

	public TaskProvider getTaskProvider() {
		return taskProvider;
	}

	private void updateContent() {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		try {
			Task.save(taskProvider.getTaskList(), baos);
			editorPane.setText(baos.toString());
		} catch (IOException e) {
			editorPane.setText(baos.toString()
					+ "\nError while loading task from the provider: "
					+ e.toString() + "\n");
		}
	}

	public void taskProviderUpdated(TaskProvider taskProvider) {
		
		// when editing, content of the task provider may be updated, so that we would override the current modification by the user (very annoying)
		if (!editing) {
			updateContent();
		}
	}
}
